#include "../../includes/model/Arquivo.h"
#include "../../includes/model/Cliente.h"

namespace model
{

	Arquivo::Arquivo( const QString &nome, const QString &nomeCompleto, const ModoAbertura &modo, QObject* parent )
		: QObject( parent ), nome( nome ), nomeCompleto( nomeCompleto ), modo( modo )
	{
		arq = new QFile( nomeCompleto );

		if( ! arq->exists() )
		{
			QString *s = new QString();

			s->append(
				QString( "Arquivo %1 nao existe").arg( nome )
			);

			delete arq;

			throw s;
		}

		if( modo == leitura )
		{
			// Atualizar a data de ultimo acesso
			arq->open( QIODevice::ReadOnly );
			size = arq->size();
			arq->close();
		} else if( modo == escrita )
		{
			arq->open( QIODevice::WriteOnly );
			size = arq->size();
			arq->close();
		}

		dados = new DadosArquivo();
	}

	void Arquivo::setCliente( Cliente *c )
	{
		QString *m = new QString();

		if( ! usuarios.contains( c ) )
		{
			usuarios.push_back( c );

		} else
		{
			m->append(
				QString( "Cliente %1 ja esta usando o arquivo %2" )
				.arg( c->getNome(), nome )
			);
			throw m;
		}

		delete m;
	}

	void Arquivo::removeCliente( Cliente *c, bool fechar )
	{
		bool contem = usuarios.contains( c );

		if( ! contem )
		{
			QString *m = new QString();
			m->append(
				QString( "Cliente %1 nao solicitou arquivo %1 ao Servidor de Arquivos" )
				.arg( c->getNome() ).arg( nome )
			);

			throw m;
		}

		usuarios.removeOne( c );

		if( fechar && usuarios.isEmpty() )
		{
			emit fecharArquivo( this );
		}
	}

	DadosArquivo Arquivo::getDadosArquivo()
	{
		QFileInfo fInfo( nomeCompleto );
		QDateTime ultimaLeitura = fInfo.lastRead(), ultimaEscrita = fInfo.lastModified();

		dados->dataCriacao = fInfo.created();
		dados->dataModificacao = fInfo.lastModified();
		dados->ultimoAcesso = ultimaLeitura < ultimaEscrita ? ultimaEscrita : ultimaLeitura;

		return *dados;
	}

	void Arquivo::atualizaDados()
	{
		if( modo == leitura )
		{
			arq->open( QIODevice::ReadOnly );
			size = arq->size();
			arq->close();
		} else if( modo == escrita )
		{
			arq->open( QIODevice::WriteOnly );
			size = arq->size();
			arq->close();
		}
	}

	QByteArray* Arquivo::getByteArray() const
	{
		if( ! arq->open( QIODevice::ReadOnly ) )
		{
			QString *s = new QString();

			s->append(
				QString( "Erro ao abrir Arquivo %1: %2.")
				.arg( nome, arq->errorString() )
			);

			throw s;
		}

		QByteArray *a = new QByteArray( arq->readAll() );

		arq->close();

		return a;
	}

	void Arquivo::apagar()
	{
		if( ! arq->exists() )
		{
			QString *s = new QString();

			s->append(
				QString( "Arquivo %1 nao existe, nao e possivel apagar." ).arg( nome )
			);

			throw s;
		}

		if( ! usuarios.isEmpty() )
		{
			QString *s = new QString();
			s->append(
				QString( "Arquivo %1 esta em uso, nao e possivel apagar." ).arg( nome )
			);

			throw s;
		}

		if( ! arq->remove() )
		{
			QString *s = new QString();
			s->append(
				QString( "Erro ao remover Arquivo %1: %2." ).arg( nome, arq->errorString() )
			);

			throw s;
		}

	}

	void Arquivo::renomear( const QString &nome, const QString &nomeCompleto )
	{
		if( usuarios.size() != 0 )
		{
			QString *s = new QString();
			s->append(
				QString("Arquivo %1 esta em uso, nao e possivel renomear.").arg( nome )
			);

			throw s;
		}

		arq->rename( this->nomeCompleto, nomeCompleto );

		this->nome = nome;
		this->nomeCompleto = nomeCompleto;
	}

	bool Arquivo::operator==( const QString& nome ) const
	{
		return this->nome == nome;
	}

	bool Arquivo::operator==( const Arquivo &other ) const
	{
		return this == &other || this->nome == other.getNome();
	}

	Arquivo::~Arquivo()
	{
		if( arq != NULL )
			delete arq;
		if( dados != NULL )
			delete dados;
	}
}
